#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include "HashSet.h"
predicate ptab[NHASH];

unsigned hash(char *s)           /*returns integer hash value of the given string*/
{
     unsigned hash = 0;
     unsigned c;
     while(c = *s++) hash = (hash*9 ^ c);
     return hash%NHASH;
}



int addPredicate(char* name,NameList *sortNames)/* add new predicate declaration to the hash table*/
{

    /*row of hash table:*/
    int hn=hash(name);
    struct predicate *ppointer = &ptab[hash(name)];
    struct predicate *lastinrow;
    /*find empty place in the hash row:*/
    while(ppointer && ppointer->name)
    {
        if(!strcmp(ppointer->name,name))
        {
            fprintf(stderr,"Multiple declarations for the same predicate\n");
            return 1;
        }
        lastinrow=ppointer;
        ppointer=ppointer->next;
    }
    /*add new predicate:*/
    ppointer=(predicate *)malloc(sizeof(predicate));
    ppointer->name=name;
    ppointer->sortNames=sortNames;
    ppointer->next=0;
    if(ptab[hash(name)].name==0)
    {
        ptab[hash(name)]=*ppointer;
    }
    else
    {
        lastinrow->next=ppointer;
    }
    return 0;
}

NameList* getSortListByName(char *name) /* returns list of sorts acceptable for the predicate with the given name*/
{

    struct predicate *ppointer = &ptab[hash(name)];
    while(ppointer && ppointer->name)
    {
        if(!strcmp(ppointer->name,name))
        {

           return ppointer->sortNames;
        }

        ppointer=ppointer->next;
    }
    return 0;
}

void deleteList(NameList *snl)  /*frees memory allocated for snl*/
{
    Name *L=snl->L;
    int i;
    for(i=0;i<snl->arity;i++) //delete names;
    {
        Name *nextL=L+1;
        free(L->name);
        L=nextL;
    }
    free(L);//delete list
    free(snl);//delete pointer
}


void deleteHashTable()           /* frees memory allocated for the hash table*/
{
    int i;
    for( i=0;i<NHASH;i++)
    {
         struct predicate *ppointer = &ptab[i];

         while(ppointer->name)
         {
             struct predicate *nextp=ppointer->next;
             free(ppointer->name);
             deleteList(ppointer->sortNames);
             ppointer=nextp;
         }

    }
}

